package com.runjian.rundo.iot.agent.common.network.tcp.handle;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.HexUtil;
import com.runjian.rundo.bmp.kernel.common.spring.context.utils.MdcUtils;
import com.runjian.rundo.iot.agent.business.publisher.DeviceMessagePublisher;
import com.runjian.rundo.iot.agent.common.codec.DeviceMessageCodec;
import com.runjian.rundo.iot.agent.common.context.DeviceMessageDecodeContext;
import com.runjian.rundo.iot.agent.common.message.DeviceMessage;
import com.runjian.rundo.iot.agent.common.network.tcp.config.ChannelAttributes;
import com.runjian.rundo.iot.agent.common.network.tcp.message.TcpMessage;
import com.runjian.rundo.iot.agent.common.network.tcp.session.TcpDeviceSession;
import com.runjian.rundo.iot.agent.common.network.tcp.session.TcpDeviceSessionManager;
import com.runjian.rundo.iot.agent.common.session.Session;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * tcp 字节流消息处理器
 *
 * @author CaoQingHua
 */
@RequiredArgsConstructor
@Slf4j
@ChannelHandler.Sharable
@Getter
@Setter
public class TcpMessageHandler extends AbstraceTcpMessageHandler {

    private final TcpDeviceSessionManager sessionManager;

    private final DeviceMessageCodec codec;

    private final DeviceMessagePublisher deviceMessagePublisher;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        try {
            // 配置日志流水号
            configTraceId(ctx);
            ByteBuf packet = (ByteBuf) msg;
            // 打印字节流
            printReceiveMessage(packet);
            // 消息解码
            List<DeviceMessage> messages = null;
            TcpDeviceSession session = sessionManager.get(ctx.channel());
            if (session != null) {
                // 消息解码
                messages = codec.decode(new DeviceMessageDecodeContext(new TcpMessage(packet), session));
            }
            if (CollUtil.isNotEmpty(messages)) {
                // 消息发送器
                messages.forEach(deviceMessagePublisher::publish);
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("[接收消息] 解码后消息为空,不需要处理");
                }
            }
        } catch (IllegalArgumentException | ParseException e) {
            log.error("[接收消息异常]，异常原因:{}, ", e.getMessage(), e);
        } catch (Exception e) {
            log.error("[接收消息异常]，异常原因:", e);
        } finally {
            ReferenceCountUtil.release(msg);
            MdcUtils.cleanTraceId();
        }
    }


    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> list) throws Exception {
        if(log.isDebugEnabled()) {
            log.debug("104协议解码开始");
        }
        int index = 0;
        int diuqiLength=0;
        while (index<in.readableBytes()) {
            if(in.getByte(index) == 0x68){
                if(diuqiLength>0){
                    //丢弃原有字符
                    if(log.isDebugEnabled()){
                        log.debug("丢充字符:{}", ByteBufUtil.hexDump(in.readBytes(diuqiLength)));
                    }
                }
                //获取指定长度
                int length=in.getUnsignedByte(index+1);
                length+=2;
                if(length<in.readableBytes()){
                    //读取指定长度的字节
                    ByteBuf byteBuf=in.readBytes(length);
                    log.debug("提取字符:{}", ByteBufUtil.hexDump(byteBuf));
                    list.add(byteBuf);
                    //读取索引
                    index+=length+1;
                }
                diuqiLength=0;
            }else {
                diuqiLength++;
                index++;
            }
        }
//        if(in.readableBytes()>0) {
//            //获取第二位侦长度
//            if(in.getUnsignedByte(0) == 0x68){
//
//            }
//
//
//            list.add(in.readRetainedSlice(in.readableBytes()));
//        }
        if(log.isDebugEnabled()) {
            log.debug("104协议解码结束,解析侦路为:{}侦",list.size());
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        // 配置日志流水号
        configTraceId(ctx);
        log.info("连接成功");
        // 激活动处理
        this.activeHandle(ctx);
    }

    public void activeHandle(ChannelHandlerContext ctx) {
        // 获取Session
        Session session = sessionManager.get(ctx.channel());
        // 触发激活动作
        codec.active(session);
        ctx.fireChannelActive();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        // 配置日志流水号
        configTraceId(ctx);
        log.info("连接关闭");
        // 获取Session
        Session session = sessionManager.get(ctx.channel());
        // 触发关闭动作
        codec.inactive(session);
        // 移除缓存
        sessionManager.remove(ctx.channel());
        ctx.fireChannelInactive();
    }







}
